package com.lifeng.mynetty.handler;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;


/**
 * Created by lifeng
 * 2017/8/31 17:49
 */
public class HttpServerHandler extends ChannelInboundHandlerAdapter{
    private static Logger logger = LoggerFactory.getLogger(HttpServerHandler.class);
    //字符编码
    private String charset;
    //内容类型
    private String contentType;
    //
    private String uri;
    protected HttpRequest request = null;
    private StringBuilder buf = new StringBuilder();

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        //一次请求会执行两次此方法
        //第一次msg是HttpRequest，第二次msg是HttpContent
        if (msg instanceof HttpRequest) {
            request = (HttpRequest) msg;
            logger.debug("request: " + request);
            String method = request.method().toString().toLowerCase();
            String requestUri = request.uri();
            int index = requestUri.indexOf("?");
            requestUri = index == -1 ? requestUri:requestUri.substring(0,requestUri.indexOf("?"));
            logger.info("method:"+method+",requestUri:"+requestUri);

            /** 所有校验均可在这里做 比如 method ，uri等*/
            /*if("get".equals(method)){
                logger.error("不支持get请求");
                return;
            }
            if(!uri.equals(requestUri)){
                logger.error("不支持uri:"+requestUri);
                return;
            }*/
            /**谷歌浏览器会有这样一次请求*/
            if("/favicon.ico".equals(requestUri)){
                logger.warn("不支持uri:"+requestUri);
                return;
            }
            QueryStringDecoder queryStringDecoder = new QueryStringDecoder(request.getUri());
            // headers
            buf.append("VERSION: " + request.getProtocolVersion() + "\r\n");
            buf.append("HOSTNAME: " + request.headers().getHost(request, "unknown") + "\r\n");
            buf.append("REQUEST_URI: " + uri + "\r\n\r\n");
            for (Map.Entry<String, String> h : request.headers()) {
                buf.append("HEADER: " + h.getKey() + " = " + h.getValue() + "\r\n");
            }
            buf.append("\r\n");
            //请求参数
            Map<String, List<String>> params = queryStringDecoder.parameters();
            if (!params.isEmpty()) {
                for (Map.Entry<String, List<String>> p : params.entrySet()) {
                    String key = p.getKey();
                    List<String> vals = p.getValue();
                    for (String val : vals) {
                        buf.append("PARAM: " + key + " = " + val + "\r\n");
                    }
                }
                buf.append("\r\n");
            }
        }
        if (msg instanceof HttpContent) {
            HttpContent content = (HttpContent) msg;
            ByteBuf byteBuf = content.content();
            logger.info("请求头:"+buf.toString()+",请求内容:"+byteBuf.toString(Charset.forName(charset)));
            String res = "你好,"+ byteBuf.toString(Charset.forName(charset));
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
                    HttpResponseStatus.OK, Unpooled.wrappedBuffer(res.getBytes(charset)));
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, contentType);
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
            if (HttpHeaders.isKeepAlive(request)) {
                response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderNames.KEEP_ALIVE);
            }
            ctx.write(response);
        }

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error(cause.getMessage());
        ctx.close();
    }

    public String getCharset() {
        return charset;
    }

    public void setCharset(String charset) {
        this.charset = charset;
    }

    public String getContentType() {
        return contentType;
    }

    public void setContentType(String contentType) {
        this.contentType = contentType;
    }

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }
}
